<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
	<meta name="theme-color" content="#33474d">
	<title>MongoDB Master：MongoDB“诟病”分析 | 失落的乐章</title>
	<link rel="stylesheet" href="/css/style.css" />
	
      <link rel="alternate" href="/atom.xml" title="失落的乐章" type="application/atom+xml">
    
</head>

<body>

	<header class="header">
		<nav class="header__nav">
			
				<a href="/archives" class="header__link">Archive</a>
			
				<a href="/tags" class="header__link">Tags</a>
			
				<a href="/atom.xml" class="header__link">RSS</a>
			
		</nav>
		<h1 class="header__title"><a href="/">失落的乐章</a></h1>
		<h2 class="header__subtitle">技术面前，永远都是学生。</h2>
	</header>

	<main>
		<article>
	
		<h1>MongoDB Master：MongoDB“诟病”分析</h1>
	
	<div class="article__infos">
		<span class="article__date">2017-10-12</span><br />
		
		
			<span class="article__tags">
			  	<a class="article__tag-link" href="/tags/MongoDB/">MongoDB</a>
			</span>
		
	</div>

	

	
		<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;近期MongoDB在Hack News上是频繁中枪。许多人更是声称恨上了MongoDB，David mytton就在他的博客中揭露了MongoDB许多现存问题。然而恨的人有之偏爱的也同样很多，作为回击：Russell Smith带来了多年工作经验的总结。Russell Smith曾担任Ops和大型网站缩放顾问并且帮助过Guardian、Experian等多家公司，MongoDB London User Group的联合创始人。作为MongoDB Master(MongoDB官方认可的MongoDB核心贡献者组织，并通过社区分享自己的专业技术)，其参与工作的基础设施单服务器每秒查询超过3万次，每天活跃数据更在1TB以上。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;下面来看Russell对MongoDB一些常见及生僻的问题做出分析：</p>
<h2 id="32位-vs-64位"><a href="#32位-vs-64位" class="headerlink" title="32位 vs 64位"></a>32位 vs 64位</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;现在大多数的服务器都对32位操作系统实现支持，更有许多新型硬件支持着允许更多RAM的64位操作系统。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;MongoDB也同时发布了32位及64位两个版本的数据库。归结于MongoDB使用的内存映射文件，32位版本只支持2G数据的存储。对于标准的Replica Set，MongoDB只拥有单一的处理策略 —— mongod。如果你想在未来储存2G以上的数据，请使用64位版本的MongoDB。如果拥有分片安装，那么32位版本同样可以使用。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;总结：使用64位版本或者理解32位版本的限制。</p>
<h2 id="文件大小限制"><a href="#文件大小限制" class="headerlink" title="文件大小限制"></a>文件大小限制</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;不同于RDBMS把数据储存在行与列中，MongoDB的数据是储存在文件中的。这些文件使用二进制存储形式，其格式为类似JSON格式的BSON格式。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;和其它的数据库一样，单个文件的储存大小是有限制的。在旧版本的MongoDB中，单个文件都限制在4M以内。而新版本的MongoDB单文件已经支持到16M大小。这样的限制也许是令人厌烦的，但是10gen的意见是：如果这项设置不停的困扰到你，那么是否你的设计模式存在着问题;或者你可以使用文件无大小限制的GridFS。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;这种情况通常的建议是避免存储过大的文件，不定期的更新数据库中存储的各种对象。而像Amazon S3或者Rackspace Cloudfiles这样的服务通常可能会是更好的选择，而非必要情况下最好别让基础设施陷入过载。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;总结：把每个文件保持在16M以下，那么一切都好。</p>
<h2 id="写入失败"><a href="#写入失败" class="headerlink" title="写入失败"></a>写入失败</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;MongoDB在默认的情况下允许高速的写入和更新，而付出的代价就是没有明确的错误通知。默认情况下多数的驱动都在做异步、“不安全”写入 —— 这就意味着驱动程序不能立即反馈错误信息，类似于MySQL的INSERT DELAYED。如果你想知道某个事情是否成功，你必须使用getLastError手动的检查错误信息。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;某些情况下如果你需要在错误发生后立刻得到错误信息，即：大多数的驱动中都很容易实现同步“安全”查询。这将谋杀掉MongoDB不同于传统数据库的优点。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;如果对比“完全安全”的同步写入你需要多一点性能，同时还想要一定程度的安全，那么你可以使用getLastError with‘j’让MongoDB只到一份日志提交后再发出错误报告通知。那么日志将以100毫秒一次的速度输出到磁盘，而不是60秒。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;总结：如果必须要写入确认，你可以使用安全写入或getLastError。</p>
<h2 id="数据结构模型的弱化不等于没有数据结构模型"><a href="#数据结构模型的弱化不等于没有数据结构模型" class="headerlink" title="数据结构模型的弱化不等于没有数据结构模型"></a>数据结构模型的弱化不等于没有数据结构模型</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;RDBMS一般都拥有一个预定义的数据结构模型：表格的行和列，每个字段都拥有名称和数据类型。如果你想给其中一行加一列，那么你必须给整个表格都添加一列。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;MongoDB则是移除了这个设置，对于Collection和文件没有强制的模型限定。这有益于快速开发及简易修改。<br>　　当然这不意味着你就可以无视结构模型的设计，一个合适的结构模型可以让你获得MongoDB的最佳性能。赶快阅读MongoDB文档，或者观看这些结构模型设计的相关视频吧!</p>
<p>　　Schema Design Basics<br>　　Schema Design at Scale<br>　　Schema Design Principles and Practice</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;总结：设计结构模型并充分利用MongoDB的特色。</p>
<h2 id="默认情况下修改语句修改的只是单个文件"><a href="#默认情况下修改语句修改的只是单个文件" class="headerlink" title="默认情况下修改语句修改的只是单个文件"></a>默认情况下修改语句修改的只是单个文件</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在传统的RDBMS中除非使用LIMIT子句，修改语句作用的将是所有匹配的地方。然而MongoDB每个查询上都默认使用等价“LIMIT 1”的设置。虽然无法做到“LIMIT 5”，但是你可以通过下面的语句整个的移除限制：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">db.people.update(&#123;age: &#123;<span class="variable">$gt</span>: 30&#125;&#125;, &#123;<span class="variable">$set</span>: &#123;past_it: <span class="literal">true</span>&#125;&#125;, <span class="literal">false</span>, <span class="literal">true</span>)</div></pre></td></tr></table></figure>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;同样在官方的驱动中还有类似的选项 —— ‘multi’。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;总结：可以通过指定多个文件的multi为true来完成多文件修改</p>
<h2 id="查询区分大小写"><a href="#查询区分大小写" class="headerlink" title="查询区分大小写"></a>查询区分大小写</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;字符串的查询可能不按预期的那样发展 —— 这归结于MongoDB默认区分大小写。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;例如：db.people.find({name: ‘Russell’})与db.people.find({name: ‘ russell‘})是不同的。在这里最理想的解决方案就是对需要查询数据进行确认。你也可以通过正则表达式进行查询，比如：db.people.find({name:/Russell/i})，但是这样会影响到性能。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;总结：查询是区分大小写的，在牺牲速度的情况下可以利用正则表达式。</p>
<h2 id="对输入的数据无容错性"><a href="#对输入的数据无容错性" class="headerlink" title="对输入的数据无容错性"></a>对输入的数据无容错性</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;当你尝试向传统数据库插入错误类型的数据，传统的数据库一般会把数据转换成预定义的类型。然而这在MongoDB中是行不通的，因为MongoDB的文件是没有预定义数据模型的。这样的话MongoDB会插入你输入的任何数据。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;总结：使用准确的数据类型。</p>
<h2 id="关于锁"><a href="#关于锁" class="headerlink" title="关于锁"></a>关于锁</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;当资源被代码的多个部分所共享时，需要确信锁必须要确保这处资源只能在一个地方被操作。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;旧版本的MongoDB (pre 2.0)拥有一个全局的写入锁。这就意味贯穿整个服务器中只有一个地方做写操作。这就可能导致数据库因为某个地方锁定超负载而停滞。这个问题在2.0版本中的得到了显著的改善，并且在当前2.2版本中得到了进一步的加强。MongoDB 2.2使用数据库级别的锁在这个问题上迈进了一大步。同样值得期待的Collection级别的锁也计划在下一个版本中推出。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;尽管如此，Russell还是认为：大多数受此限制的应用程序于其说是受MongoDB影响，还不如说是程序本身的问题来的更直接。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;总结：使用最新的稳定版本才能获得最高的性能。</p>
<h2 id="关于包"><a href="#关于包" class="headerlink" title="关于包"></a>关于包</h2><p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;在类Ubuntu和Debian系统上安装时，许多人都出现过“过时版本”这样的问题。解决方案很简单：使用10gen官方库，那么在Ubuntu和Debian上安装也会像在Fedora和Centos上安装一样流畅。</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;总结：使用拥有大多数最新版本的官方包。</p>

	

	
		<span class="different-posts"><a href="/2017/10/12/MongoDB/11. MongoDB Master：MongoDB“诟病”分析/" onclick="window.history.go(-1); return false;">⬅️ Go back </a></span>

	

</article>

	</main>

	<footer class="footer">
	<div class="footer-content">
		
	      <div class="footer__element">
	<p>Hi there, <br />welcome to my Blog glad you found it. Have a look around, will you?</p>
</div>

	    
	      <div class="footer__element">
	<h5>Check out</h5>
	<ul class="footer-links">
		<li class="footer-links__link"><a href="/archives">Archive</a></li>
		
		  <li class="footer-links__link"><a href="/atom.xml">RSS</a></li>
	    
		<li class="footer-links__link"><a href="/about">about page</a></li>
		<li class="footer-links__link"><a href="/tags">Tags</a></li>
		<li class="footer-links__link"><a href="/categories">Categories</a></li>
	</ul>
</div>

	    

		<div class="footer-credit">
			<span>© 2017 失落的乐章 | Powered by <a href="https://hexo.io/">Hexo</a> | Theme <a href="https://github.com/HoverBaum/meilidu-hexo">MeiliDu</a></span>
		</div>

	</div>


</footer>



</body>

</html>
